// Copyright 2007 Google, Inc. All Rights Reserved.

package com.google.jessewilson.codesearch.commandlinesearch;

import com.google.jessewilson.codesearch.api.CodeFile;
import com.google.jessewilson.codesearch.api.Line;
import com.google.jessewilson.codesearch.io.Path;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Parse a generic result line using the configuration for guidance. 
 *
 * @author jessewilson
 */
class ResultParser {

  private ClsSearchProviderBackend searchProvider;
  private final Matcher matcher;
  private final ClsConfiguration configuration;

  public ResultParser(ClsSearchProviderBackend searchProvider) {
    this(searchProvider.getConfiguration());
    this.searchProvider = searchProvider;
  }

  public ResultParser(ClsConfiguration configuration) {
    this.configuration = configuration;
    this.matcher = Pattern.compile(configuration.getParseLineRegex()).matcher("");
  }

  public Line parse(String resultLine) throws ParseFailedException {
    matcher.reset(resultLine);
    if (!matcher.matches()) {
      throw new ParseFailedException(matcher.pattern(), resultLine);
    }

    if(matcher.groupCount() < configuration.getFilePathMatch()
        || matcher.groupCount() < configuration.getLineNumberMatch()
        || matcher.groupCount() < configuration.getLineValueMatch()) {
      throw new ParseFailedException(matcher.pattern(), resultLine);
    }

    try {
      String path = matcher.group(configuration.getFilePathMatch());
      String lineNumber = matcher.group(configuration.getLineNumberMatch());
      String lineValue = matcher.group(configuration.getLineValueMatch());

      CodeFile codeFile = new CodeFile();
      codeFile.setPath(Path.fromString(path));
      codeFile.setId(path);
      codeFile.setSearchProvider(searchProvider);

      Line result = new Line();
      result.setCodeFile(codeFile);
      result.setLineNumber(Integer.parseInt(lineNumber) - 1);
      result.setLineValue(lineValue);

      return result;
    } catch(RuntimeException e) {
      throw new ParseFailedException(resultLine, e);
    }
  }

  public class ParseFailedException extends java.lang.Exception {
    public ParseFailedException(Pattern pattern, String resultLine) {
      super("Failed to match pattern \""
          + pattern + "\" against result \"" + resultLine + "\"");
    }
    public ParseFailedException(String resultLine, RuntimeException cause) {
      super("Error while parsing result \"" + resultLine + "\"", cause);
    }
  }
}
